home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / listings / v_02_02 / 2n02071a < prev    next >
Text File  |  1990-12-17  |  3KB  |  91 lines

  1. /*
  2.  * example of a self-modifying .EXE file
  3.  * written for Turbo C 2.0, by Bob Bybee, June 1990
  4.  *
  5.  * usage:
  6.  *   selfexe (no arguments) prints the current data area
  7.  *
  8.  *   selfexe arg1 arg2...   changes the .EXE file to contain
  9.  *                          those args in the data area
  10.  */
  11.  
  12. #include <stdio.h>
  13. #include <stdlib.h>
  14. #include <string.h>
  15. #include <io.h>
  16. #include <fcntl.h>
  17.  
  18. /* Declare an area for the initializing data which will
  19.  * be modified.  This would probably be a structure,
  20.  * in a more complex program.
  21.  */
  22.  
  23. #define KEY_LENGTH 10               /* length of "key" string */
  24. static char init_data[512] =
  25.     "INIT_DATA\0"                   /* the "key" string */
  26.     "This is the original data.\0"; /* some data */
  27.  
  28. #define BLOCK_SIZE 256
  29. char block_buf[BLOCK_SIZE * 2];
  30.  
  31. void main( int argc, char **argv )
  32. {
  33.     char new_data[80], *p;
  34.     int fh, nbytes, i, got_it;
  35.     long pos;
  36.  
  37.     /* First, the program opens its own .EXE file.
  38.      * Its name is provided in argv[0].
  39.      */
  40.     if ((fh = open(argv[0], O_RDWR|O_BINARY)) == -1)
  41.         {
  42.         printf("Can't open myself!\n");
  43.         exit(1);
  44.         }
  45.  
  46.     /* If there were arguments on the command line,
  47.      * concatenate them into a single string in new_data[].
  48.      */
  49.     if (argc > 1)
  50.         {
  51.         new_data[0] = '\0';     /* empty the new_data string */
  52.         for (i = 1; i < argc; ++i)
  53.             {
  54.             strcat(new_data, argv[i]);
  55.             strcat(new_data, " ");
  56.             }
  57.         }
  58.  
  59.     /* Search the .EXE file, by reading 2 blocks at a time,
  60.      * one block apart.  (Read 0, 1, then 1, 2, ...)
  61.      * This works even if the key string overlaps a block boundary.
  62.      */
  63.     for (got_it = 0, pos = 0L; !got_it; pos += BLOCK_SIZE)
  64.         {
  65.         lseek(fh, pos, SEEK_SET);
  66.         nbytes = read(fh, block_buf, BLOCK_SIZE * 2);
  67.         if (nbytes <= 0)
  68.             break;      /* the search failed! */
  69.  
  70.         for (p = block_buf, i = 0; i < BLOCK_SIZE; ++i, ++p)
  71.             if (memcmp(init_data, p, KEY_LENGTH) == 0)
  72.                 {
  73.                 got_it = 1;
  74.                 printf("Found it: file position 0x%04lx\n", pos + i);
  75.                 printf("Data in file is: \"%s\"\n",
  76.                     p + KEY_LENGTH);
  77.  
  78.                 if (argc > 1)
  79.                     {           /* write new data */
  80.                     printf("Writing new data...\n");
  81.                     lseek(fh, pos + i + KEY_LENGTH, SEEK_SET);
  82.                     write(fh, new_data, strlen(new_data) + 1);
  83.                     }
  84.                 break;
  85.                 }
  86.         }
  87.  
  88.     close(fh);
  89.     exit(0);
  90. }
  91.